<!--
 * @Description: 用户任务执行监听器表单
 * @Author: DHL
 * @Date: 2022-06-17 11:06:07
 * @LastEditors: DHL
 * @LastEditTime: 2022-10-14 15:47:17
-->
<template>
  <tw-drawer
    v-model="visible"
    title="任务监听器"
    size="700px"
    :sticky="false"
    appendToBody
    @close="handleClose"
  >
    <div class="listeners-form-wrapper">
      <el-form ref="dbFormRef" :model="dbForm" :rules="rules" label-width="90px">
        <el-form-item label="事件类型" prop="event">
          <el-select v-model="dbForm.event" clearable placeholder="请选择事件类型">
            <el-option
              v-for="item in Object.keys(eventTypeObject)"
              :key="item"
              :label="eventTypeObject[item]"
              :value="item"
            />
          </el-select>
        </el-form-item>

        <el-form-item label="监听器ID" prop="id">
          <el-input v-model="dbForm.id" :rows="2" clearable placeholder="请输入监听器ID"></el-input>
        </el-form-item>

        <el-form-item label="监听器类型" prop="listenerType">
          <el-select v-model="dbForm.listenerType" clearable placeholder="请选择监听器类型">
            <el-option
              v-for="item in Object.keys(listenerTypeObject)"
              :key="item"
              :label="listenerTypeObject[item]"
              :value="item"
            />
          </el-select>
        </el-form-item>

        <el-form-item label="Java类" prop="class" v-if="dbForm.listenerType === 'classListener'">
          <el-input
            v-model="dbForm.class"
            :rows="2"
            type="textarea"
            clearable
            placeholder="请输入Java类"
          ></el-input>
        </el-form-item>

        <el-form-item
          label="表达式"
          prop="expression"
          v-if="dbForm.listenerType === 'expressionListener'"
        >
          <el-input
            v-model="dbForm.expression"
            :rows="2"
            type="textarea"
            clearable
            placeholder="请输入表达式"
          ></el-input>
        </el-form-item>

        <el-form-item
          label="代理表达式"
          prop="delegateExpression"
          v-if="dbForm.listenerType === 'delegateExpressionListener'"
        >
          <el-input
            v-model="dbForm.delegateExpression"
            :rows="2"
            type="textarea"
            clearable
            placeholder="请输入代理表达式"
          ></el-input>
        </el-form-item>

        <template v-if="dbForm.listenerType === 'scriptListener'">
          <el-form-item label="脚本格式" prop="scriptFormat">
            <el-input
              v-model="dbForm.scriptFormat"
              :rows="2"
              type="textarea"
              clearable
              placeholder="请输入脚本格式"
            ></el-input>
          </el-form-item>

          <el-form-item label="脚本类型" prop="scriptType">
            <el-select v-model="dbForm.scriptType" clearable placeholder="请选择脚本类型">
              <el-option label="内联脚本" value="inlineScript" />
              <el-option label="外部脚本" value="externalScript" />
            </el-select>
          </el-form-item>

          <el-form-item label="脚本内容" prop="value" v-if="dbForm.scriptType === 'inlineScript'">
            <el-input
              v-model="dbForm.value"
              :rows="2"
              type="textarea"
              clearable
              placeholder="请输入脚本内容"
            ></el-input>
          </el-form-item>

          <el-form-item
            label="资源地址"
            prop="resource"
            v-if="dbForm.scriptType === 'externalScript'"
          >
            <el-input
              v-model="dbForm.resource"
              :rows="2"
              type="textarea"
              clearable
              placeholder="请输入资源地址"
            ></el-input>
          </el-form-item>
        </template>
      </el-form>

      <el-divider />

      <div class="process-panel-tab__content-title">
        <div>
          <svg-icon className="process-icon" iconClass="appStoreFill"></svg-icon>
          <span>注入字段</span>
        </div>
        <el-button type="primary" size="small" @click="handleFieldOpen()">
          <svg-icon className="process-icon" iconClass="plus"></svg-icon>
          添加字段
        </el-button>
      </div>

      <div class="mt10 process-panel-tab__content-table">
        <el-table :data="fieldsList" size="small" border>
          <el-table-column type="index" label="序号" width="50px" />
          <el-table-column label="字段名称" prop="name" min-width="100px" show-overflow-tooltip />
          <el-table-column
            label="字段类型"
            prop="fieldType"
            min-width="100px"
            show-overflow-tooltip
            :formatter="(row:any) => fieldTypeObject[row.fieldType]"
          />
          <el-table-column
            label="字段值/表达式"
            prop="expression"
            min-width="100px"
            show-overflow-tooltip
            :formatter="(row:any) => row.string || row.expression"
          />
          <el-table-column label="操作" prop="action" width="100px" align="center">
            <template #default="scope">
              <el-button
                link
                type="warning"
                title="编辑"
                @click="handleFieldEdit(scope.row, scope.$index)"
              >
                <svg-icon className="process-icon" iconClass="editSquare"></svg-icon>
              </el-button>

              <el-button
                link
                type="danger"
                title="移除"
                @click="handleFieldDelete(scope.row, scope.$index)"
              >
                <svg-icon className="process-icon" iconClass="delete"></svg-icon>
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>

    <template #footer>
      <el-button @click="handleClose()">取 消</el-button>
      <el-button type="primary" @click="handleSubmitForm()">保 存</el-button>
    </template>
  </tw-drawer>

  <!-- 字段配置弹框 -->
  <tw-dialog
    v-model="fieldVisible"
    title="字段配置"
    width="400px"
    :showZoom="false"
    @close="handleCloseField"
  >
    <el-form ref="dbFieldFormRef" :model="dbFieldForm" :rules="fieldRules" label-width="90px">
      <el-form-item label="字段名称" prop="name">
        <el-input v-model="dbFieldForm.name" clearable placeholder="请输入字段名称"></el-input>
      </el-form-item>
      <el-form-item label="字段类型" prop="fieldType">
        <el-select v-model="dbFieldForm.fieldType" clearable placeholder="请选择字段类型">
          <el-option
            v-for="item in Object.keys(fieldTypeObject)"
            :key="item"
            :label="fieldTypeObject[item]"
            :value="item"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="字段值" prop="string" v-if="dbFieldForm.fieldType === 'string'">
        <el-input v-model="dbFieldForm.string" clearable placeholder="请输入字段值"></el-input>
      </el-form-item>
      <el-form-item label="表达式" prop="expression" v-if="dbFieldForm.fieldType === 'expression'">
        <el-input
          v-model="dbFieldForm.expression"
          :rows="2"
          type="textarea"
          clearable
          placeholder="请输入表达式"
        ></el-input>
      </el-form-item>
    </el-form>

    <template #footer>
      <el-button @click="handleCloseField()">取 消</el-button>
      <el-button type="primary" @click="handleFieldSubmit()">确 定</el-button>
    </template>
  </tw-dialog>
</template>

<script lang="ts">
  export default { name: 'ListenersForm' }
</script>

<script setup lang="ts">
  import { ElMessage, ElMessageBox } from 'element-plus'
  import { assign, cloneDeep } from 'lodash-es'
  import { reactive, ref } from 'vue'
  import { eventType, fieldType, initListenerForm, listenerType } from './listenersUtils'

  //////////////////////////////////////////////////
  // 参数
  //////////////////////////////////////////////////
  const emit = defineEmits(['listenersFormSubmit'])

  //////////////////////////////////////////////////
  // 属性
  //////////////////////////////////////////////////
  const visible = ref(false)

  const listenerTypeObject: any = ref(listenerType)
  const eventTypeObject: any = ref(eventType)

  const dbFormRef = ref()

  const dbForm = reactive({
    id: '',
    event: '',
    listenerType: '',
    class: '',
    expression: '',
    delegateExpression: '',
    scriptFormat: '',
    scriptType: '',
    value: '',
    resource: '',
    fields: [] as any
  })

  const rules = reactive({
    id: [
      {
        required: true,
        message: '请输入监听器ID',
        trigger: 'blur'
      }
    ],
    event: [
      {
        required: true,
        message: '请选择事件类型',
        trigger: 'blur'
      }
    ],
    listenerType: [
      {
        required: true,
        message: '请选择监听器类型',
        trigger: 'blur'
      }
    ],
    class: [
      {
        required: true,
        message: '请输入Java类',
        trigger: 'blur'
      }
    ],
    expression: [
      {
        required: true,
        message: '请输入表达式',
        trigger: 'blur'
      }
    ],
    delegateExpression: [
      {
        required: true,
        message: '请输入代理表达式',
        trigger: 'blur'
      }
    ],
    scriptFormat: [
      {
        required: true,
        message: '请输入脚本格式',
        trigger: 'blur'
      }
    ],
    scriptType: [
      {
        required: true,
        message: '请选择脚本类型',
        trigger: 'blur'
      }
    ],
    value: [
      {
        required: true,
        message: '请输入脚本内容',
        trigger: 'blur'
      }
    ],
    resource: [
      {
        required: true,
        message: '请输入资源地址',
        trigger: 'blur'
      }
    ]
  })

  //////////////////////////////////////////////////
  // 函数
  //////////////////////////////////////////////////
  /**
   * 打开弹框
   */
  function handleOpen(actionParam: string, rowParam: any) {
    if (actionParam === 'add') {
      assign(dbForm, {
        event: '',
        listenerType: '',
        class: '',
        expression: '',
        delegateExpression: '',
        scriptFormat: '',
        scriptType: '',
        value: '',
        resource: ''
      })

      fieldsList.value = []
    } else {
      assign(dbForm, initListenerForm(rowParam))

      if (rowParam.fields) {
        fieldsList.value = rowParam.fields.map((field: { string: string }) => ({
          ...field,
          fieldType: field.string ? 'string' : 'expression'
        }))
      }
    }
    visible.value = true
  }

  /**
   * 关闭弹框
   */
  function handleClose() {
    visible.value = false
  }

  /**
   * 保存监听配置
   */
  function handleSubmitForm() {
    dbFormRef.value.validate((valid: boolean) => {
      if (valid) {
        emit('listenersFormSubmit', cloneDeep(dbForm))
      }
    })
  }

  /**
   * 暴露函数
   */
  defineExpose({ handleOpen, handleClose })

  //////////////////////////////////////////////////
  // 注入字段
  //////////////////////////////////////////////////
  const fieldsList: any = ref([])

  const fieldTypeObject: any = ref(fieldType)

  const fieldVisible = ref(false)

  const dbFieldForm = reactive({
    name: '',
    fieldType: '',
    string: '',
    expression: ''
  })

  const dbFieldFormRef = ref()

  let fieldIndex = -1

  const fieldRules = reactive({
    name: [
      {
        required: true,
        message: '请输入字段名称',
        trigger: 'blur'
      }
    ],
    fieldType: [
      {
        required: true,
        message: '请选择字段类型',
        trigger: 'blur'
      }
    ],
    string: [
      {
        required: true,
        message: '请输入字段值',
        trigger: 'blur'
      }
    ],
    expression: [
      {
        required: true,
        message: '请输入表达式',
        trigger: 'blur'
      }
    ]
  })

  /**
   * 新增字段
   */
  function handleFieldOpen() {
    assign(dbFieldForm, {
      name: '',
      fieldType: '',
      string: '',
      expression: ''
    })
    fieldIndex = -1
    fieldVisible.value = true
  }

  function handleCloseField() {
    fieldVisible.value = false
  }

  /**
   * 字段表单提交
   */
  function handleFieldSubmit() {
    dbFieldFormRef.value.validate((valid: boolean) => {
      if (valid) {
        if (fieldIndex === -1) {
          fieldsList.value.push(cloneDeep(dbFieldForm))
          dbForm.fields.push(cloneDeep(dbFieldForm))
        } else {
          fieldsList.value.splice(fieldIndex, 1, cloneDeep(dbFieldForm))
          dbForm.fields.splice(fieldIndex, 1, cloneDeep(dbFieldForm))
        }
        handleCloseField()
      }
    })
  }

  /**
   * 编辑字段
   */
  function handleFieldEdit(row: any, index: number) {
    assign(dbFieldForm, cloneDeep(row))
    fieldIndex = index
    fieldVisible.value = true
  }

  /**
   * 除该字段
   */
  function handleFieldDelete(row: any, index: number) {
    ElMessageBox.confirm('确认移除该字段吗?', '移除提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(() => {
        fieldsList.value.splice(index, 1)
        dbForm.fields.splice(index, 1)
      })
      .catch(() => {
        ElMessage.info('操作被取消了')
      })
  }
</script>

<style scoped lang="scss">
  .listeners-form-wrapper {
    padding: 10px 15px 10px 10px;

    .mt10 {
      margin-top: 10px;
    }

    .process-panel-tab__content-title {
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .el-divider {
      margin: 10px 0px;
    }

    .svg-icon {
      width: 15px;
      height: 15px;
      margin-right: 5px;
    }
  }
</style>
